package com.skstudio.nuprint.lpd;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;

import com.skstudio.nuprint.LpdService;

public class CommandReceiveJob extends CommandHandler {
	public CommandReceiveJob(Reader in, Writer out) {
		super(in, out);
	}
	
	@Override
	public void execute(byte[] command) throws Exception {
		String[] opds = CommandHandler.parseOperands(command);
		String queueName = opds[0];
		
		LpdPrintJob job = receivePrintJob(queueName);
		if (job != null) LpdQueue.getInstance().addPrintJob(job);
	}
	
	private LpdPrintJob receivePrintJob(String queueName) throws Exception
	{
		LpdPrintJob printJob = new LpdPrintJob(queueName);

		//Reads control file or data file, which ever that arrives first
		for (int i = 1; i <= 2; i++)
		{
			byte[] subCmd = readSubCommand();
			if (subCmd == null || subCmd.length == 0) return null;
			LpdService.writeCommand(subCmd);
			
			try {
				switch(subCmd[0]) {
					case 2:			
						setControlFile(subCmd, printJob.getCtrlFile());
						break;
					case 3:
						setDataFile(subCmd, printJob.getDataFile());
						break;
					default:
						throw new Exception("unknown sub command");
				}
				acknowledge(LpdCommand.GOOD_ACK); //ACK_GOOD
			}catch(Exception e) {
				acknowledge(LpdCommand.BAD_ACK); //ACK_GOOD
				throw e;
			}
		}

		return printJob;
	}
	
	protected byte[] readSubCommand()  {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		
		try {
			do {
				int data = mReader.read();
				if (data == -1) break;
				
				baos.write(data);
				if (data == 10) break;  //LineFeed signals the end of a command
			} while(true);
			acknowledge(LpdCommand.GOOD_ACK); //ACK_GOOD
		} catch (Exception e) {
			e.printStackTrace();
			try {
				acknowledge(LpdCommand.BAD_ACK);
			} catch (IOException e1) {
				e1.printStackTrace();
			}
			return null;
		}

		return baos.toByteArray();
	}
	
	protected void setControlFile(byte[] subCmd, LpdPrintJob.LpdControlFile ctrlFile) throws IOException {
		String[] opds = CommandHandler.parseOperands(subCmd);
		
		String ctrlFileSize = opds[0];
		ctrlFile.size = Integer.parseInt(ctrlFileSize);
		
		String ctrlHeader = opds[1];
		String first3Chars = ctrlHeader.substring(0, 3); //should be "cfA"
		first3Chars.equalsIgnoreCase("cfA");
		ctrlFile.jobNumber = ctrlHeader.substring(3, 6);
		ctrlFile.hostName = ctrlHeader.substring(6);	
		byte[] cFile = readFile(0);
		LpdService.writeCommand(cFile);
		
		ctrlFile.setControlFileCommands(cFile);
	}
	
	protected void setDataFile(byte[] subCmd, LpdPrintJob.LpdDataFile dataFile) throws IOException {
		String[] opds = CommandHandler.parseOperands(subCmd);

		String dataFileSize = opds[0];
		dataFile.size = Integer.parseInt(dataFileSize);
		
		String dataHeader = opds[1];
		String first3Chars = dataHeader.substring(0, 3); //should be "dfA"
		first3Chars.equalsIgnoreCase("dfA");
		dataFile.jobNumber = dataHeader.substring(3, 6);
		dataFile.hostName = dataHeader.substring(6);
		dataFile.contents = readFile(dataFile.size);
		
		LpdService.writeCommand(dataFile.contents);
	}
	
	protected byte[] readFile(int size) throws IOException {
		int count = 0;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		do {
			int data = mReader.read();
			if (data == -1 || data == 0) break;
			
			baos.write(data);
			count++;
			
			if (size == count) break;
		} while(true);	
		
		return baos.toByteArray();
	}
}
